﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.ServiceModel.DomainServices.Client;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls;
using System.Xml;
using System.Xml.Linq;

using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;

using NetBay.Core.BusinessEntities;
using NetBay.Core.BusinessEntities.Workflow;

using Rio.Applications.Web.Services;
using Rio.Framework.Localisation;
using Rio.Framework.Pages;
using Rio.Framework.Pages.Context;
using Rio.Manager.Application.Extensions;
using Rio.Manager.Application.ViewModel.BaseClass;

using Telerik.Windows.Data;
using Rio.Framework.Pages.Controls;
using Rio.Manager.Application.Utils;
using Rio.Framework.Pages.ChildWindows;

namespace Rio.Manager.Application.ViewModel.FolderTypeAdministration
{
    public class NewWorkflowTabViewModel : TabViewModelBase
    {
        #region Fields

        private string _ActivateEndDateText;
        private string _AutomaticReceiversText;
        private string _ClearFormText;
        private string _currentRules;
        private WorkflowDefinition _currentWorkflowDefinition;
        private DateTime _dateToDeactivateOldWorkflow;
        private string _DefineText;
        private string _DeleteText;
        private string _EditManagementRulesText;
        private List<NetBay.Core.BusinessEntities.Group> _groups;
        private string _IndexationReceiversText;
        private bool _isChildCreation;
        private bool _isEditMode;
        private string _ManagementRulesText;
        private WorkflowDefinition _parentWorkflowDefinition;
        private string _SaveAsModelText;
        private string _SaveModificationsText;
        private string _SaveText;
        private ObservableCollection<WorkflowAction> _selectedAction;
        private ObservableCollection<WorkflowCondition> _selectedConditions;
        private FolderType _selectedFolderType;
        private Index _selectedRecipientIndex;
        private WorkflowModel _selectedWorkflowModel;
        private string _TreatmentsText;
        private string _TriggersText;
        private string _WorkflowDescriptionText;
        private string _WorkflowTypeText;
        private string _WorkflowHierarchicalText;
        private string _WorkflowClassicalText;
        private string _WorkflowEndDateText;
        private string _WorkflowLabelText;
        private string _WorkflowLinksText;
        private string _WorkflowLinks_Description;
        private string _WorkflowLinks_Name;
        private ObservableCollection<WorkflowModel> _workflowModels;
        private string _WorkflowReceiversText;
        private WorkflowDefinition _workflowSourceForEdition;
        private string _WorkflowStartDateText;
        private string _WorkflowTypesText;

        #endregion Fields

        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="NewWorkflowTabViewModel"/> class.
        /// </summary> 
        public NewWorkflowTabViewModel()
            : base()
        {
            CanCloseTab = true;
            TabIcon = new Uri("/Rio.Manager.Application;component/Assets/Images/newworkflow.png", UriKind.Relative);
        }

        /// <summary>
        ///  Initializes a new instance of the <see cref="NewWorkflowTabViewModel"/> class.
        /// </summary>
        /// <param name="p_IsChildCreation">Initialize as child (true / false)</param>
        public NewWorkflowTabViewModel(bool p_IsChildCreation)
            : this()
        {
            IsChildCreation = p_IsChildCreation;
        }

        #endregion Constructors

        #region Properties

        public string ActivateEndDateText
        {
            get { return _ActivateEndDateText; }
            set
            {
                _ActivateEndDateText = value;
                RaisePropertyChanged("ActivateEndDateText");
            }
        }

        public string AutomaticReceiversText
        {
            get { return _AutomaticReceiversText; }
            set
            {
                _AutomaticReceiversText = value;
                RaisePropertyChanged("AutomaticReceiversText");
            }
        }

        public RelayCommand ClearDataFormCommand
        {
            get;
            set;
        }

        public string ClearFormText
        {
            get { return _ClearFormText; }
            set
            {
                _ClearFormText = value;
                RaisePropertyChanged("ClearFormText");
            }
        }

        public WorkflowDefinition CurrentWorkflowDefinition
        {
            get { return _currentWorkflowDefinition; }
            set
            {
                _currentWorkflowDefinition = value;

                _currentWorkflowDefinition.PropertyChanged += delegate(object sender, PropertyChangedEventArgs e)
                {
                    OpenReceiversIndexWindowCommand.RaiseCanExecuteChanged();
                    OpenGroupsWindowCommand.RaiseCanExecuteChanged();
                    SetToNullEndDateCommand.RaiseCanExecuteChanged();
                    OpenWorkflowRulesEditorWindowCommand.RaiseCanExecuteChanged();
                    RaisePropertyChanged("CurrentWorkflowDefinition");
                };

                SetToNullEndDateCommand.RaiseCanExecuteChanged();
                OpenReceiversIndexWindowCommand.RaiseCanExecuteChanged();
                OpenWorkflowRulesEditorWindowCommand.RaiseCanExecuteChanged();
                OpenGroupsWindowCommand.RaiseCanExecuteChanged();
                RaisePropertyChanged("CurrentWorkflowDefinition");
            }
        }

        public DateTime DateToDeactivateOldWorkflow
        {
            get { return _dateToDeactivateOldWorkflow; }
            set
            {
                _dateToDeactivateOldWorkflow = value.Date;
                RaisePropertyChanged("DateToDeactivateOldWorkflow");
            }
        }

        public string DefineText
        {
            get { return _DefineText; }
            set
            {
                _DefineText = value;
                RaisePropertyChanged("DefineText");
            }
        }

        public string DeleteText
        {
            get { return _DeleteText; }
            set
            {
                _DeleteText = value;
                RaisePropertyChanged("DeleteText");
            }
        }

        public RelayCommand DeactivateWorkFlowDefinitionCommand
        {
            get;
            set;
        }

        public string EditManagementRulesText
        {
            get { return _EditManagementRulesText; }
            set
            {
                _EditManagementRulesText = value;
                RaisePropertyChanged("EditManagementRulesText");
            }
        }

        public List<NetBay.Core.BusinessEntities.Group> Groups
        {
            get { return _groups; }
            set
            {
                _groups = value;
                RaisePropertyChanged("Groups");
            }
        }

        public string IndexationReceiversText
        {
            get { return _IndexationReceiversText; }
            set
            {
                _IndexationReceiversText = value;
                RaisePropertyChanged("IndexationReceiversText");
            }
        }

        public RelayCommand InitializationCommand
        {
            get;
            set;
        }

        public bool IsChildCreation
        {
            get { return _isChildCreation; }
            set
            {
                _isChildCreation = value;
                RaisePropertyChanged("IsChildCreation");
            }
        }

        public bool IsEditMode
        {
            get { return _isEditMode; }
            private set
            {
                _isEditMode = value;
                RaisePropertyChanged("IsEditMode");
            }
        }

        public string ManagementRulesText
        {
            get { return _ManagementRulesText; }
            set
            {
                _ManagementRulesText = value;
                RaisePropertyChanged("ManagementRulesText");
            }
        }

        public RelayCommand OpenGroupsWindowCommand
        {
            get;
            set;
        }

        public RelayCommand OpenReceiversIndexWindowCommand
        {
            get;
            set;
        }

        public RelayCommand OpenWorkflowRulesEditorWindowCommand
        {
            get;
            set;
        }

        /// <summary>
        /// Set the parent definition for a child
        /// </summary>
        public WorkflowDefinition ParentWorkflowDefinition
        {
            get { return _parentWorkflowDefinition; }
            set
            {
                _parentWorkflowDefinition = value;
                RaisePropertyChanged("ParentWorkflowDefinition");
            }
        }

        public string SaveAsModelText
        {
            get { return _SaveAsModelText; }
            set
            {
                _SaveAsModelText = value;
                RaisePropertyChanged("SaveAsModelText");
            }
        }

        public string SaveModificationsText
        {
            get { return _SaveModificationsText; }
            set
            {
                _SaveModificationsText = value;
                RaisePropertyChanged("SaveModificationsText");
            }
        }

        public RelayCommand SaveModifiedWorkflowDefinitionCommand
        {
            get;
            set;
        }

        public string SaveText
        {
            get { return _SaveText; }
            set
            {
                _SaveText = value;
                RaisePropertyChanged("SaveText");
            }
        }

        public RelayCommand SaveWorkflowAsModelCommand
        {
            get;
            set;
        }

        public RelayCommand SaveWorkflowDefinitionCommand
        {
            get;
            set;
        }

        public ObservableCollection<WorkflowAction> SelectedActions
        {
            get { return _selectedAction; }
            set
            {
                _selectedAction = value;
                RaisePropertyChanged("SelectedActions");
            }
        }

        public ObservableCollection<WorkflowCondition> SelectedConditions
        {
            get { return _selectedConditions; }
            set
            {
                _selectedConditions = value;
                RaisePropertyChanged("SelectedConditions");
            }
        }

        public override FolderType SelectedFolderType
        {
            get { return base.SelectedFolderType; }
            set
            {
                base.SelectedFolderType = value;

                if (CurrentWorkflowDefinition != null)
                {
                    OpenReceiversIndexWindowCommand.RaiseCanExecuteChanged();
                }

                RaisePropertyChanged("SelectedFolderType");
            }
        }

        public Index SelectedRecipientIndex
        {
            get { return _selectedRecipientIndex; }
            set
            {
                _selectedRecipientIndex = value;
                RaisePropertyChanged("SelectedRecipientIndex");
            }
        }

        public WorkflowModel SelectedWorkflowModel
        {
            get { return _selectedWorkflowModel; }
            set
            {
                _selectedWorkflowModel = value;

                RaisePropertyChanged("SelectedWorkflowModel");
                RaisePropertyChanged("WorkflowActions");

                OpenWorkflowRulesEditorWindowCommand.RaiseCanExecuteChanged();
            }
        }

        public RelayCommand SetToNullEndDateCommand
        {
            get;
            set;
        }

        public string TreatmentsText
        {
            get { return _TreatmentsText; }
            set
            {
                _TreatmentsText = value;
                RaisePropertyChanged("TreatmentsText");
            }
        }

        public string TriggersText
        {
            get { return _TriggersText; }
            set
            {
                _TriggersText = value;
                RaisePropertyChanged("TriggersText");
            }
        }

        public QueryableCollectionView WorkflowActions
        {
            get
            {
                if (ParentWorkflowDefinition != null && IsChildCreation)
                {
                    return new QueryableCollectionView(ParentWorkflowDefinition.Actions.Select(i => i.ConvertToWorkflowCondition()));
                }
                else if (SelectedWorkflowModel != null)
                {
                    return new QueryableCollectionView(SelectedWorkflowModel.Conditions);
                }
                else
                {
                    return null;
                }
            }
        }

        public string WorkflowDescriptionText
        {
            get { return _WorkflowDescriptionText; }
            set
            {
                _WorkflowDescriptionText = value;
                RaisePropertyChanged("WorkflowDescriptionText");
            }
        }

        public string WorkflowTypeText
        {
            get { return _WorkflowTypeText; }
            set
            {
                _WorkflowTypeText = value;
                RaisePropertyChanged("WorkflowTypeText");
            }
        }

        public string WorkflowHierarchicalText
        {
            get { return _WorkflowHierarchicalText; }
            set
            {
                _WorkflowHierarchicalText = value;
                RaisePropertyChanged("WorkflowHierarchicalText");
            }
        }

        public string WorkflowClassicalText
        {
            get { return _WorkflowClassicalText; }
            set
            {
                _WorkflowClassicalText = value;
                RaisePropertyChanged("WorkflowClassicalText");
            }
        }

        public string WorkflowEndDateText
        {
            get { return _WorkflowEndDateText; }
            set
            {
                _WorkflowEndDateText = value;
                RaisePropertyChanged("WorkflowEndDateText");
            }
        }

        public string WorkflowLabelText
        {
            get { return _WorkflowLabelText; }
            set
            {
                _WorkflowLabelText = value;
                RaisePropertyChanged("WorkflowLabelText");
            }
        }

        public string WorkflowLinksText
        {
            get { return _WorkflowLinksText; }
            set
            {
                _WorkflowLinksText = value;
                RaisePropertyChanged("WorkflowLinksText");
            }
        }

        public string WorkflowLinks_Description
        {
            get { return _WorkflowLinks_Description; }
            set
            {
                _WorkflowLinks_Description = value;
                RaisePropertyChanged("WorkflowLinks_Description");
            }
        }

        public string WorkflowLinks_Name
        {
            get { return _WorkflowLinks_Name; }
            set
            {
                _WorkflowLinks_Name = value;
                RaisePropertyChanged("WorkflowLinks_Name");
            }
        }

        public ObservableCollection<WorkflowModel> WorkflowModels
        {
            get { return _workflowModels; }
            set
            {
                _workflowModels = value;
                RaisePropertyChanged("WorkflowModels");
            }
        }

        public string WorkflowReceiversText
        {
            get { return _WorkflowReceiversText; }
            set
            {
                _WorkflowReceiversText = value;
                RaisePropertyChanged("WorkflowReceiversText");
            }
        }

        public WorkflowDefinition WorkflowSourceForEdition
        {
            get { return _workflowSourceForEdition; }
            private set
            {
                _workflowSourceForEdition = value;
                RaisePropertyChanged("WorkflowSourceForEdition");
            }
        }

        public string WorkflowStartDateText
        {
            get { return _WorkflowStartDateText; }
            set
            {
                _WorkflowStartDateText = value;
                RaisePropertyChanged("WorkflowStartDateText");
            }
        }

        public string WorkflowTypesText
        {
            get { return _WorkflowTypesText; }
            set
            {
                _WorkflowTypesText = value;
                RaisePropertyChanged("WorkflowTypesText");
            }
        }

        #endregion Properties

        #region Methods

        /// <summary>
        /// Clones to child workflow.
        /// </summary>
        /// <returns></returns>
        public NewWorkflowTabViewModel CloneToChildWorkflow()
        {
            return new NewWorkflowTabViewModel()
            {
                IsChildCreation = true,
                CurrentWorkflowDefinition = new WorkflowDefinition(),
                SelectedOrganization = SelectedOrganization,
                SelectedFolderType = SelectedFolderType,
                SelectedWorkflowModel = SelectedWorkflowModel,
            };
        }

        /// <summary>
        /// Inits the commands.
        /// </summary>
        public override void InitCommands()
        {
            InitializationCommand = new RelayCommand(Initialization);

            ClearDataFormCommand = new RelayCommand(ClearDataForm);

            SaveWorkflowDefinitionCommand = new RelayCommand(SaveWorkflowDefinitionCmd);

            SaveWorkflowAsModelCommand = new RelayCommand(SaveWorkflowAsModel);

            DeactivateWorkFlowDefinitionCommand = new RelayCommand(DeactivateDefinition);

            OpenGroupsWindowCommand = new RelayCommand(
                OpenGroupsWindow,
                () => CurrentWorkflowDefinition != null && CurrentWorkflowDefinition.ReceiversType == ReceiverType.Auto ? true : false);

            OpenReceiversIndexWindowCommand = new RelayCommand(
                OpenReceiversIndexWindow,
                () => SelectedFolderType != null && CurrentWorkflowDefinition != null && CurrentWorkflowDefinition.ReceiversType == ReceiverType.Index ? true : false);

            SetToNullEndDateCommand = new RelayCommand(
                () => CurrentWorkflowDefinition.EndDate = null,
                () => CurrentWorkflowDefinition != null);

            SaveModifiedWorkflowDefinitionCommand = new RelayCommand(() =>
                {
                    if (ValidateWorkflowDefinition())
                    {
                        NotificationMessageAction<DateTime> notificationMessageAction = new NotificationMessageAction<DateTime>(
                            DateToDeactivateOldWorkflow,
                            String.Empty,
                            ValidateModifiedWorkflowDefinition);

                        Messenger.Default.Send<NotificationMessageAction<DateTime>>(notificationMessageAction);
                    }
                });

            OpenWorkflowRulesEditorWindowCommand = new RelayCommand(
                OpenWorkflowRulesWindow,
                () => SelectedWorkflowModel != null);
        }

        /// <summary>
        /// Opens the workflow rules window.
        /// </summary>
        private void OpenWorkflowRulesWindow()
        {
            NotificationMessageAction<string> notificationMessageAction = new NotificationMessageAction<string>(
                String.IsNullOrWhiteSpace(CurrentWorkflowDefinition.Rules) ? SelectedWorkflowModel.Rules : CurrentWorkflowDefinition.Rules,
                rules => CurrentWorkflowDefinition.Rules = rules);

            Messenger.Default.Send<NotificationMessageAction<string>>(notificationMessageAction);
        }

        /// <summary>
        /// Inits the labels.
        /// </summary>
        public override void InitLabels()
        {
            TabTitle = Resx.GetLabel(ResxRioManager.MODELIZE_WORKFLOW);

            ActivateEndDateText = Resx.GetLabel(ResxRioManager.NEWWORKFLOWTABVIEWMODEL_ACTIVATEENDDATETEXT);
            AutomaticReceiversText = Resx.GetLabel(ResxRioManager.NEWWORKFLOWTABVIEWMODEL_AUTOMATICRECEIVERSTEXT);
            ClearFormText = Resx.GetLabel(ResxRioManager.NEWWORKFLOWTABVIEWMODEL_CLEARFORMTEXT);
            DefineText = Resx.GetLabel(ResxRioManager.NEWWORKFLOWTABVIEWMODEL_DEFINETEXT);
            DeleteText = Resx.GetLabel(ResxRioManager.MANAGEWORKFLOWTABVIEWMODEL_DEACTIVATEWORKFLOWTEXT);
            EditManagementRulesText = Resx.GetLabel(ResxRioManager.NEWWORKFLOWTABVIEWMODEL_EDITMANAGEMENTRULESTEXT);
            IndexationReceiversText = Resx.GetLabel(ResxRioManager.NEWWORKFLOWTABVIEWMODEL_INDEXATIONRECEIVERSTEXT);
            ManagementRulesText = Resx.GetLabel(ResxRioManager.NEWWORKFLOWTABVIEWMODEL_MANAGEMENTRULESTEXT);
            SaveAsModelText = Resx.GetLabel(ResxRioManager.NEWWORKFLOWTABVIEWMODEL_SAVEASMODELTEXT);
            SaveModificationsText = Resx.GetLabel(ResxRioManager.NEWWORKFLOWTABVIEWMODEL_SAVEMODIFICATIONSTEXT);
            SaveText = Resx.GetLabel(ResxRioManager.NEWWORKFLOWTABVIEWMODEL_SAVETEXT);
            TreatmentsText = Resx.GetLabel(ResxRioManager.NEWWORKFLOWTABVIEWMODEL_TREATMENTSTEXT);
            TriggersText = Resx.GetLabel(ResxRioManager.NEWWORKFLOWTABVIEWMODEL_TRIGGERSTEXT);
            WorkflowDescriptionText = Resx.GetLabel(ResxRioManager.NEWWORKFLOWTABVIEWMODEL_WORKFLOWDESCRIPTIONTEXT);
            WorkflowTypeText = Resx.GetLabel(ResxRioManager.NEWWORKFLOWTABVIEWMODEL_WORKFLOWTYPETEXT);
            WorkflowHierarchicalText = Resx.GetLabel(ResxRioManager.NEWWORKFLOWTABVIEWMODEL_WORKFLOWHIERARCHICALTEXT);
            WorkflowClassicalText = Resx.GetLabel(ResxRioManager.NEWWORKFLOWTABVIEWMODEL_WORKFLOWCLASSICALTEXT);
            WorkflowEndDateText = Resx.GetLabel(ResxRioManager.NEWWORKFLOWTABVIEWMODEL_WORKFLOWENDDATETEXT);
            WorkflowLabelText = Resx.GetLabel(ResxRioManager.NEWWORKFLOWTABVIEWMODEL_WORKFLOWLABELTEXT);
            WorkflowLinksText = Resx.GetLabel(ResxRioManager.NEWWORKFLOWTABVIEWMODEL_WORKFLOWLINKSTEXT);
            WorkflowLinks_Description = Resx.GetLabel(ResxRioManager.NEWWORKFLOWTABVIEWMODEL_WORKFLOWLINKS_DESCRIPTION);
            WorkflowLinks_Name = Resx.GetLabel(ResxRioManager.NEWWORKFLOWTABVIEWMODEL_WORKFLOWLINKS_NAME);
            WorkflowReceiversText = Resx.GetLabel(ResxRioManager.NEWWORKFLOWTABVIEWMODEL_WORKFLOWRECEIVERSTEXT);
            WorkflowStartDateText = Resx.GetLabel(ResxRioManager.NEWWORKFLOWTABVIEWMODEL_WORKFLOWSTARTDATETEXT);
            WorkflowTypesText = Resx.GetLabel(ResxRioManager.NEWWORKFLOWTABVIEWMODEL_WORKFLOWTYPESTEXT);
        }

        /// <summary>
        /// Sets the edit mode.
        /// </summary>
        /// <param name="d">The d.</param>
        public void SetEditMode(WorkflowDefinition d)
        {
            IsEditMode = true;

            WorkflowSourceForEdition = d;
            CurrentWorkflowDefinition = WorkflowSourceForEdition.Clone();

            if (d.ParentId != null)
            {
                BusyIndicator.Clear();
                BusyIndicator.AddBusyTask();

                BusinessEntitiesDomainContext ds = new BusinessEntitiesDomainContext();
                var query = ds.GetWorkflowDefinitionByIdQuery(d.ParentId.Value);

                ds.Load<WorkflowDefinition>(
                    query,
                    result =>
                    {
                        BusyIndicator.RemoveBusyTask();

                        if (!result.HasError)
                        {
                            IsChildCreation = true;
                            SetParentDefinition(result.Entities.FirstOrDefault());
                        }
                    },
                    null);
            }
        }

        /// <summary>
        /// Set the parent workflow definition
        /// </summary>
        /// <param name="d"></param>
        public void SetParentDefinition(WorkflowDefinition d)
        {
            ParentWorkflowDefinition = d;
        }

        /// <summary>
        /// Clears the data form.
        /// </summary>
        private void ClearDataForm()
        {
            IsEditMode = false;

            CurrentWorkflowDefinition = new WorkflowDefinition()
            {
                ReceiversType = ReceiverType.Auto,
                StartDate = DateTime.Now,
                EndDate = null,
                IsHierarchical = false,
            };

            WorkflowSourceForEdition = CurrentWorkflowDefinition;
            SelectedActions = new ObservableCollection<WorkflowAction>();
            SelectedConditions = new ObservableCollection<WorkflowCondition>();

            SelectedRecipientIndex = null;
            SelectedWorkflowModel = null;

            Groups = null;


            OpenReceiversIndexWindowCommand.RaiseCanExecuteChanged();
            OpenGroupsWindowCommand.RaiseCanExecuteChanged();
            SetToNullEndDateCommand.RaiseCanExecuteChanged();
            OpenWorkflowRulesEditorWindowCommand.RaiseCanExecuteChanged();
        }

        /// <summary>
        /// Deactivates the definition.
        /// </summary>
        private void DeactivateDefinition()
        {
            //Show popup to deactivate the definition
            DateTimePickerChildWindow dateTimePickerChildWindow = new DateTimePickerChildWindow()
            {
                DescriptionText = Resx.GetLabel(ResxRioManager.WORKFLOWDEFINITION_DEACTIVATE_CONFIRMATION),
                DateTimePickerText = Resx.GetLabel(ResxRioManager.MANAGEWORKFLOWTABVIEWMODEL_DEACTIVATEDATEWORKFLOWTEXT) + " :",
                SelectedDateTime = DateTime.Now
            };

            dateTimePickerChildWindow.Closed += (s, e) =>
            {
                if (((DateTimePickerChildWindow)s).DialogResult == true)
                {
                    //Deactivate the definition at the specified date
                    BusyIndicator.Clear();
                    BusyIndicator.AddBusyTask();

                    BusinessEntitiesDomainContext businessEntitiesDomainContext = GlobalWebContext.BusinessEntitiesDomainContext;
                    businessEntitiesDomainContext.DeactivateDefinition(
                        _currentWorkflowDefinition.Identifier, ((DateTimePickerChildWindow)s).SelectedDateTime,
                        (retr) =>
                        {
                            BusyIndicator.RemoveBusyTask();

                            if (retr.HasError || !retr.Value.Value)
                            {
                                ShowModalDialog(
                                    Resx.GetLabel(ResxCommon.ERROR),
                                    Resx.GetLabel(ResxRioManager.WORKFLOWDEFINITION_DELETE_ERROR),
                                    MessageBoxButtons.Ok,
                                    MessageBoxIcon.Error);
                            }
                            else
                            {
                                ShowModalDialog(
                                    String.Empty,
                                    Resx.GetLabel(ResxRioManager.WORKFLOWDEFINITION_DELETE_SUCCESS),
                                    MessageBoxButtons.Ok,
                                    MessageBoxIcon.Information);

                                ClearDataForm();

                                NeedToRefreshWorkflowList();
                            }
                        },
                        null);

                }
            };

            dateTimePickerChildWindow.ShowDialog();
        }

        /// <summary>
        /// Deactivates and save modified workflow definition.
        /// </summary>
        /// <param name="keepChilds">The keep childs.</param>
        private void DeactivateAndSaveModifiedWorkflowDefinition(bool keepChilds = false)
        {
            BusinessEntitiesDomainContext businessEntitiesDomainContext = GlobalWebContext.BusinessEntitiesDomainContext;
            businessEntitiesDomainContext.DeactivateDefinition(
                WorkflowSourceForEdition.Identifier,
                DateToDeactivateOldWorkflow,
                (result) =>
                {
                    if (result.HasError || !result.Value.Value)
                    {
                        MessageBox.Show(String.Format("{0} : {1}", Resx.GetLabel(ResxCommon.ERROR), result.Error.Message));
                    }
                    else
                    {
                        SaveWorkflowDefinition(keepChilds);
                    }
                }, null);
        }

        /// <summary>
        /// Initializations this instance.
        /// </summary>
        private void Initialization()
        {
            InitLabels();

            if (!IsEditMode)
            {
                CurrentWorkflowDefinition = new WorkflowDefinition()
                {
                    ReceiversType = ReceiverType.Auto,
                    StartDate = DateTime.Now,
                    EndDate = null
                };

                SelectedActions = new ObservableCollection<WorkflowAction>();
                SelectedConditions = new ObservableCollection<WorkflowCondition>();

                SelectedRecipientIndex = null;
                SelectedWorkflowModel = null;

                Groups = null;
            }
            else
            {
                DateToDeactivateOldWorkflow = DateTime.Now;
            }

            OpenReceiversIndexWindowCommand.RaiseCanExecuteChanged();
            OpenGroupsWindowCommand.RaiseCanExecuteChanged();
            SetToNullEndDateCommand.RaiseCanExecuteChanged();
            OpenWorkflowRulesEditorWindowCommand.RaiseCanExecuteChanged();

            LoadWorkflowModels();
        }

        /// <summary>
        /// Loads the stored informations like conditions, actions
        /// </summary>
        private void LoadActionsAndConditionsSaved()
        {
            /*
             * Load Actions
             */

            BusinessEntitiesDomainContext businessEntitiesDomainContext = GlobalWebContext.BusinessEntitiesDomainContext;
            var actionsQuery = businessEntitiesDomainContext.GetDefinitionActionsQuery(CurrentWorkflowDefinition.Identifier);

            businessEntitiesDomainContext.Load(
                actionsQuery,
                retr =>
                {
                    if (retr.HasError || retr.Entities == null)
                    {
                        MessageBox.Show(String.Format("{0} : {1}", Resx.GetLabel(ResxCommon.ERROR), retr.Error.Message));
                    }
                    else
                    {
                        SelectedActions =
                            new ObservableCollection<WorkflowAction>(from modelAction in SelectedWorkflowModel.Actions
                                                                     from workflowAction in retr.Entities
                                                                     where modelAction.ActionOrConditionId == workflowAction.ActionOrConditionId
                                                                     select modelAction);

                        Messenger.Default.Send(
                            new NotificationMessage<ObservableCollection<WorkflowAction>>(SelectedActions,
                            String.Empty));
                    }
                },
                null);

            /*
             * Load Conditions
             */

            businessEntitiesDomainContext = GlobalWebContext.BusinessEntitiesDomainContext;
            var conditionsQuery = businessEntitiesDomainContext.GetDefinitionConditionsQuery(CurrentWorkflowDefinition.Identifier);

            businessEntitiesDomainContext.Load<WorkflowCondition>(
                conditionsQuery,
                delegate(LoadOperation<WorkflowCondition> retr)
                {
                    if (retr.HasError
                        || retr.Entities == null)
                    {
                        MessageBox.Show(String.Format("{0} : {1}",
                                                      Resx.GetLabel(ResxCommon.ERROR),
                                                      retr.Error.Message));
                    }
                    else
                    {
                        if (IsChildCreation && ParentWorkflowDefinition != null)
                        {
                            SelectedConditions = new ObservableCollection<WorkflowCondition>(from parentAction in ParentWorkflowDefinition.Actions
                                                                                             from workflowCondition in retr.Entities
                                                                                             where parentAction.ActionOrConditionId == workflowCondition.ActionOrConditionId
                                                                                             select parentAction.ConvertToWorkflowCondition());
                        }
                        else
                        {
                            SelectedConditions =
                               new ObservableCollection<WorkflowCondition>(
                                   SelectedWorkflowModel.Conditions.Where(
                                       i => retr.Entities.Any(j => j.ActionOrConditionId == i.ActionOrConditionId))
                                       .ToList());
                        }

                        Messenger.Default.Send<NotificationMessage<ObservableCollection<WorkflowCondition>>>(
                            new NotificationMessage<ObservableCollection<WorkflowCondition>>(SelectedConditions,
                                                                                             String.Empty));
                    }
                },
                null);
        }

        /// <summary>
        /// Loads the workflow models.
        /// </summary>
        private void LoadWorkflowModels()
        {
            BusyIndicator.Clear();
            BusyIndicator.AddBusyTask();

            BusinessEntitiesDomainContext businessEntitiesDomainContext = GlobalWebContext.BusinessEntitiesDomainContext;
            var query = businessEntitiesDomainContext.GetWorkflowModelsQuery();

            businessEntitiesDomainContext.Load(
                query,
                delegate(LoadOperation<WorkflowModel> retr)
                {
                    BusyIndicator.RemoveBusyTask();

                    if (!retr.HasError && retr.Entities != null)
                    {
                        WorkflowModels = new ObservableCollection<WorkflowModel>(retr.Entities);

                        if (IsEditMode)
                        {
                            SelectedWorkflowModel = WorkflowModels.Where(wkf => wkf.Identifier == WorkflowSourceForEdition.ModelId).SingleOrDefault();

                            LoadActionsAndConditionsSaved();
                        }
                    }
                },
                null);
        }

        /// <summary>
        /// Needs to refresh workflow list.
        /// </summary>
        private void NeedToRefreshWorkflowList()
        {
            //Refresh if ManageWorkflow View is open
            Messenger.Default.Send<NotificationMessage>(new NotificationMessage("refresh"));
        }

        /// <summary>
        /// Opens the groups window.
        /// </summary>
        private void OpenGroupsWindow()
        {
            NotificationMessageAction<List<NetBay.Core.BusinessEntities.Group>> notificationMessageAction = new NotificationMessageAction<List<NetBay.Core.BusinessEntities.Group>>(
                Groups == null ? null : Groups.Select(i => i.Identifier).ToList(),
                Groups,
                String.Empty,
                g => Groups = g);
            Messenger.Default.Send<NotificationMessageAction<List<NetBay.Core.BusinessEntities.Group>>>(notificationMessageAction);
        }

        /// <summary>
        /// Opens the receivers index window.
        /// </summary>
        private void OpenReceiversIndexWindow()
        {
            NotificationMessageAction<Index> notificationMessageAction = new NotificationMessageAction<Index>(
                SelectedFolderType.LstIndex.Where((index) => index.Type == (int)IndexDomainServiceEnums.IndexType.ListeOfRecipient).ToList(),
                SelectedRecipientIndex,
                String.Empty,
                i => SelectedRecipientIndex = i);

            Messenger.Default.Send<NotificationMessageAction<Index>>(notificationMessageAction);
        }

        /// <summary>
        /// Saves the workflow as template.
        /// </summary>
        private void SaveWorkflowAsModel()
        {
            if (ValidateWorkflowModel())
            {
                BusyIndicator.Clear();
                BusyIndicator.AddBusyTask();

                CurrentWorkflowDefinition.WorkflowType = SelectedWorkflowModel.WorkflowType;

                CurrentWorkflowDefinition.AssemblyName = SelectedWorkflowModel.AssemblyName;
                CurrentWorkflowDefinition.ClassName = SelectedWorkflowModel.ClassName;
                CurrentWorkflowDefinition.ModelId = SelectedWorkflowModel.Identifier;
                CurrentWorkflowDefinition.WorkflowType = SelectedWorkflowModel.WorkflowType;
                CurrentWorkflowDefinition.Rules = String.IsNullOrWhiteSpace(CurrentWorkflowDefinition.Rules) ? SelectedWorkflowModel.Rules : CurrentWorkflowDefinition.Rules;

                BusinessEntitiesDomainContext businessEntitiesDomainContext = GlobalWebContext.BusinessEntitiesDomainContext;

                businessEntitiesDomainContext.AddWorkflowModel(
                    CurrentWorkflowDefinition.ConvertToModel(),
                    SelectedActions.Select(item => item.ActionOrConditionId),
                    SelectedConditions.Select(item => item.ActionOrConditionId),
                    SaveWorkflowAsModelCallback,
                    null);
            }
        }

        /// <summary>
        /// Callback of SaveWorkflowAsModel.
        /// </summary>
        /// <param name="result">The result.</param>
        private void SaveWorkflowAsModelCallback(InvokeOperation<ReturnBoolean> result)
        {
            BusyIndicator.RemoveBusyTask();

            if (result.HasError || !result.Value.Value)
            {
                ShowModalDialog(
                    Resx.GetLabel(ResxCommon.ERROR),
                    Resx.GetLabel(ResxRioManager.WORKFLOWMODEL_SAVE_ERROR),
                    MessageBoxButtons.Ok,
                    MessageBoxIcon.Error);
            }
            else
            {
                ShowModalDialog(
                    String.Empty,
                    Resx.GetLabel(ResxRioManager.WORKFLOWMODEL_SAVE_SUCCESS),
                    MessageBoxButtons.Ok,
                    MessageBoxIcon.Information);

                ClearDataForm();

                NeedToRefreshWorkflowList();
            }
        }

        /// <summary>
        /// Saves the workflow definition CMD.
        /// </summary>
        private void SaveWorkflowDefinitionCmd()
        {
            SaveWorkflowDefinition(false);
        }

        /// <summary>
        /// Saves the workflow definition.
        /// </summary>
        private void SaveWorkflowDefinition(bool keepChilds = false)
        {
            if (ValidateWorkflowDefinition())
            {
                BusyIndicator.Clear();
                BusyIndicator.AddBusyTask();

                CurrentWorkflowDefinition.WorkflowType = SelectedWorkflowModel.WorkflowType;

                CurrentWorkflowDefinition.AssemblyName = SelectedWorkflowModel.AssemblyName;
                CurrentWorkflowDefinition.ClassName = SelectedWorkflowModel.ClassName;
                CurrentWorkflowDefinition.FolderTypeId = SelectedFolderType.Identifier;
                CurrentWorkflowDefinition.ModelId = SelectedWorkflowModel.Identifier;
                CurrentWorkflowDefinition.Rules = String.IsNullOrWhiteSpace(CurrentWorkflowDefinition.Rules) ? SelectedWorkflowModel.Rules : CurrentWorkflowDefinition.Rules;

                if (_isChildCreation && ParentWorkflowDefinition != null)
                {
                    CurrentWorkflowDefinition.ParentId = ParentWorkflowDefinition.Identifier;
                }

                Dictionary<long, bool> actions = new Dictionary<long, bool>();
                SelectedActions.ToList().ForEach(item => actions.Add(item.ActionOrConditionId, item.IsTrigger));

                BusinessEntitiesDomainContext businessEntitiesDomainContext = GlobalWebContext.BusinessEntitiesDomainContext;

                if (CurrentWorkflowDefinition.ReceiversType == ReceiverType.Auto)
                {
                    businessEntitiesDomainContext.AddWorkflowDefinitionWithGroups(
                        CurrentWorkflowDefinition,
                        actions,
                        SelectedConditions.Select(item => item.ActionOrConditionId),
                        Groups.Select(item => item.Identifier),
                        keepChilds,
                        SaveWorkflowDefinitionCallback,
                        null);
                }
                else
                {
                    businessEntitiesDomainContext.AddWorkflowDefinitionWithIndex(
                        CurrentWorkflowDefinition,
                        actions,
                        SelectedConditions.Select(item => item.ActionOrConditionId),
                        SelectedRecipientIndex.Indentifier,
                        keepChilds,
                        SaveWorkflowDefinitionCallback,
                        null);
                }
            }
        }

        /// <summary>
        /// Callback of SaveWorkflowDefinition.
        /// </summary>
        /// <param name="result">The result.</param>
        private void SaveWorkflowDefinitionCallback(InvokeOperation<ReturnBoolean> result)
        {
            BusyIndicator.RemoveBusyTask();

            if (result.HasError || !result.Value.Value)
            {
                ShowModalDialog(
                    Resx.GetLabel(ResxCommon.ERROR),
                    Resx.GetLabel(ResxRioManager.WORKFLOWDEFINITION_SAVE_ERROR),
                    MessageBoxButtons.Ok,
                    MessageBoxIcon.Error);
            }
            else
            {
                ShowModalDialog(
                    String.Empty,
                    Resx.GetLabel(ResxRioManager.WORKFLOWDEFINITION_SAVE_SUCCESS),
                    MessageBoxButtons.Ok,
                    MessageBoxIcon.Information);

                ClearDataForm();

                NeedToRefreshWorkflowList();
            }
        }

        /// <summary>
        /// Validates the workflow.
        /// </summary>
        private bool ValidateWorkflowDefinition()
        {
            bool isValid = true;

            #region Organization Validation

            if (SelectedOrganization == null)
            {
                isValid = false;
                AddError(
                    "SelectedOrganization",
                    Resx.GetLabel(ResxRioManager.ORGANISATION_ERROR));
            }
            else
            {
                RemoveError(
                    "SelectedOrganization",
                    Resx.GetLabel(ResxRioManager.ORGANISATION_ERROR));
            }

            #endregion

            #region FolderType Validation

            if (SelectedFolderType == null)
            {
                isValid = false;
                AddError(
                    "SelectedFolderType",
                    Resx.GetLabel(ResxRioManager.FOLDERTYPE_ERROR));
            }
            else
            {
                RemoveError(
                    "SelectedFolderType",
                    Resx.GetLabel(ResxRioManager.FOLDERTYPE_ERROR));
            }

            #endregion

            isValid = ValidateWorkflowModel();

            #region Start and End Dates

            if (CurrentWorkflowDefinition.EndDate != null)
            {
                if (CurrentWorkflowDefinition.StartDate > CurrentWorkflowDefinition.EndDate)
                {
                    AddError(
                        "CurrentWorkflowDefinition.StartDate",
                        Resx.GetLabel(ResxRioManager.NEWWORKFLOWTABVIEWMODEL_STARTDATE));
                    isValid = false;
                }
                else
                {
                    RemoveError(
                           "CurrentWorkflowDefinition.StartDate",
                            Resx.GetLabel(ResxRioManager.NEWWORKFLOWTABVIEWMODEL_STARTDATE));
                }
            }

            #endregion

            #region Receivers Type Validation

            if (CurrentWorkflowDefinition.ReceiversType == 0)
            {
                AddError(
                    "CurrentWorkflowDefinition.ReceiversType",
                    Resx.GetLabel(ResxRioManager.RECEIVERSTYPES_ERROR));
                isValid = false;
            }
            else
            {
                RemoveError(
                    "CurrentWorkflowDefinition.ReceiversType",
                    Resx.GetLabel(ResxRioManager.RECEIVERSTYPES_ERROR));
            }

            #endregion

            #region Groups Validation

            if (CurrentWorkflowDefinition.ReceiversType == ReceiverType.Auto && (Groups == null || Groups.Count == 0))
            {
                isValid = false;
                AddError(
                    "Groups",
                    Resx.GetLabel(ResxRioManager.RECEIVERSGROUP_ERROR));
            }
            else
            {
                RemoveError(
                    "Groups",
                    Resx.GetLabel(ResxRioManager.RECEIVERSGROUP_ERROR));
            }

            #endregion

            #region Index Receivers Validation

            if (CurrentWorkflowDefinition.ReceiversType == ReceiverType.Index && SelectedRecipientIndex == null)
            {
                isValid = false;
                AddError(
                    "SelectedRecipientIndex",
                    Resx.GetLabel(ResxRioManager.NEWWORKFLOWTABVIEWMODEL_SELECTEDRECIPIENT));
            }
            else
            {
                RemoveError(
                    "SelectedRecipientIndex",
                    Resx.GetLabel(ResxRioManager.NEWWORKFLOWTABVIEWMODEL_SELECTEDRECIPIENT));
            }

            #endregion

            RaisePropertyChanged("Errors");

            return isValid;
        }

        /// <summary>
        /// Validates the workflow model.
        /// </summary>
        /// <returns></returns>
        private bool ValidateWorkflowModel()
        {
            bool isValid = true;

            #region Workflow Model Validation

            if (SelectedWorkflowModel == null)
            {
                isValid = false;
                AddError(
                    "SelectedWorkflowModel",
                    Resx.GetLabel(ResxRioManager.WORKFLOWMODEL_ERROR));
            }
            else
            {
                RemoveError(
                    "SelectedWorkflowModel",
                    Resx.GetLabel(ResxRioManager.WORKFLOWMODEL_ERROR));

                #region Conditions Validation

                if (SelectedWorkflowModel.Conditions.Count > 0 && (SelectedConditions == null || SelectedConditions.Count == 0))
                {
                    isValid = false;
                    AddError(
                        "SelectedConditions",
                        Resx.GetLabel(ResxRioManager.TRIGGERS_ERROR));
                }
                else
                {
                    RemoveError(
                        "SelectedConditions",
                        Resx.GetLabel(ResxRioManager.TRIGGERS_ERROR));
                }

                #endregion

                #region Actions Validation

                if (SelectedWorkflowModel.Actions.Count > 0 && (SelectedActions == null || SelectedActions.Count == 0))
                {
                    isValid = false;
                    AddError(
                        "SelectedActions",
                        Resx.GetLabel(ResxRioManager.TREATMENTS_ERROR));
                }
                else
                {
                    RemoveError(
                        "SelectedActions",
                        Resx.GetLabel(ResxRioManager.TREATMENTS_ERROR));
                }

                #endregion
            }

            #endregion

            #region Name Validation

            if (String.IsNullOrWhiteSpace(CurrentWorkflowDefinition.Name))
            {
                isValid = false;
                AddError(
                    "CurrentWorkflowDefinition.Name",
                    Resx.GetLabel(ResxRioManager.WORKFLOWDEFINITIONNAME_ERROR));
            }
            else
            {
                RemoveError(
                    "CurrentWorkflowDefinition.Name",
                    Resx.GetLabel(ResxRioManager.WORKFLOWDEFINITIONNAME_ERROR));
            }

            #endregion

            #region Description Validation

            if (String.IsNullOrWhiteSpace(CurrentWorkflowDefinition.Description))
            {
                isValid = false;
                AddError(
                    "CurrentWorkflowDefinition.Description",
                    Resx.GetLabel(ResxRioManager.WORKFLOWDEFINITIONDESCRIPTION_ERROR));
            }
            else
            {
                RemoveError(
                    "CurrentWorkflowDefinition.Description",
                    Resx.GetLabel(ResxRioManager.WORKFLOWDEFINITIONDESCRIPTION_ERROR));
            }

            #endregion

            RaisePropertyChanged("Errors");

            return isValid;
        }

        /// <summary>
        /// Saves the modified workflow definition.
        /// </summary>
        /// <param name="deactivatedDateTime">The deactivated date time.</param>
        private void ValidateModifiedWorkflowDefinition(DateTime deactivatedDateTime)
        {
            DateToDeactivateOldWorkflow = deactivatedDateTime;

            if (ValidateWorkflowDefinition())
            {
                // show message to keep childs 
                if (WorkflowSourceForEdition.HasChild)
                {
                    //Check if the child(s) condition(s) match the current definition action(s)
                    var childs = ValidateActionsAndConditionsChildsLink();
                    if (childs.Count > 0)
                    {
                        string childList = string.Empty;
                        foreach (var item in childs)
                        {
                            childList += string.Format("- {0} \n", item.Name);
                        }

                        //The child(s) cannot be keep
                        MessageBoxChildWindow message = new MessageBoxChildWindow(String.Empty,
                                                                                  "Les flux fils suivant ne seront plus valides, souhaitez vous continuer et perdre TOUS les flux fils?",
                                                                                  MessageBoxButtons.OkCancel,
                                                                                  MessageBoxIcon.Warning);
                        message.Show();
                        message.Closed += (s, ev) =>
                        {
                            if (message.Result == MessageBoxResult.OK)
                            {
                                DeactivateAndSaveModifiedWorkflowDefinition(false);
                            }
                        };

                    }
                    else
                    {
                        //Keep child(s) question
                        MessageBoxChildWindow message = new MessageBoxChildWindow(String.Empty,
                                                Resx.GetLabel(ResxRioManager.WORKFLOWDEFINITION_KEEPCHILDS_QUESTION),
                                                MessageBoxButtons.YesNo,
                                                MessageBoxIcon.Warning);
                        message.Show();
                        message.Closed += (s, ev) =>
                        {
                            if (message.Result == MessageBoxResult.Yes)
                            {
                                DeactivateAndSaveModifiedWorkflowDefinition(true);
                            }
                            else
                            {
                                DeactivateAndSaveModifiedWorkflowDefinition(false);
                            }
                        };
                    }
                }
                else
                {
                    //no childs
                    DeactivateAndSaveModifiedWorkflowDefinition(false);
                }
            }
        }

        /// <summary>
        /// Validates the actions and conditions childs link.
        /// </summary>
        /// <returns></returns>
        private List<WorkflowDefinition> ValidateActionsAndConditionsChildsLink()
        {
            List<WorkflowDefinition> unvalidateChilds = new List<WorkflowDefinition>();

            //For each parent actions
            foreach (var child in WorkflowSourceForEdition.Childs)
            {
                foreach (var childCondition in child.Conditions)
                {
                    bool result = SelectedActions.Any(p => p.ActionOrConditionId == childCondition.ActionOrConditionId);
                    if (!result)
                    {
                        unvalidateChilds.Add(child);
                        break;
                    }
                }
            }

            return unvalidateChilds;
        }

        #endregion Methods

    }
}